home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Hacks / Hacks ’97 / Melt the Control Strip / source code / temp_cs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-06-28  |  19.3 KB  |  622 lines  |  [TEXT/MPS ]

  1. /*
  2.  * temperature manager control strip module
  3.  * based on: ControlStripSample.c,a sample Control Strip module © by macDTS '93
  4.  * melt algorithm ideas by Benoit Schillings
  5.  * melt implementation by Dave Blundell
  6.  * control strip by Brian Gaeke
  7.  */
  8.  
  9. #include <Icons.h>
  10. #include <ControlStrip.h>
  11. #include "temp_cs.h"
  12. #include <A4Stuff.h>
  13. #include <math.h>
  14. #include <LowMem.h>
  15. #include <stdio.h>
  16. #include <Notification.h>
  17. #include "layermgr.h"
  18. #define PI 3.1415926535897932384626499
  19.  
  20.  
  21. //////////////////////////////////////////////////////////////////////////////////////////////
  22. //
  23. //    global variables
  24.  
  25. typedef struct Globals {                                // global variables we use while we exist
  26.     Handle            thermoIcon;                            //    handle to thermo icon
  27.     PicHandle        popupArrowPicture;                    //    picture to show we have a popup menu
  28.     Handle            helpStrings;                        //    balloon help strings for each state
  29.     short            helpStringIndex;                    //    which help string to display
  30.     short            whichIcon;                            //    which icon we're drawing
  31.     MenuHandle        configMenu;                            //    menu to select display options
  32.     short            level;                 // current thermo value
  33.     short            goingdown;
  34.     unsigned long    lasttime;
  35.     short             didNot;
  36.     NMRec            currNotReq;
  37.     Str255            happystring;
  38. } Globals;
  39.  
  40.  
  41. //////////////////////////////////////////////////////////////////////////////////////////////
  42. //
  43. //    information saved across restarts
  44.  
  45. typedef struct SavedSettings {
  46.     OSType            signature;                            //    signature to verify it's for this module
  47.     short            whichIcon;                            //    which icon we're drawing
  48. } SavedSettings;
  49.  
  50.  
  51. //////////////////////////////////////////////////////////////////////////////////////////////
  52. //
  53. //    prototypes
  54.  
  55. long Initialize();
  56. void CleanUp(Globals **globs);
  57. void DrawThermo(Globals *gb, Rect *statusRect);
  58. void GetCurrentIcon(Globals *gb);
  59. long HandleMouseClick(Globals *gb, Rect *statusRect);
  60. short SavePreferences(Globals *gb);
  61. int do_shift(const int numpix, const int numrows);
  62. Boolean IsWholeScreen(WindowPeek wl);
  63. WindowPtr GetWindowToMelt(void);
  64. void PostStrNotification(Globals *gb,short rsrcId, short index);
  65. void IdleCall(Globals *gb);
  66.  
  67. /* Dave's and Benoit's Melt Algorithm.
  68.  *
  69.  * do_shift uses getpixelXY and putpixelXY to move pixels in the melting image.
  70.  * numpix is the number of pixels across; numrows is the number of rows down.
  71.  * as a precondition, the port is set to the port we are melting. 
  72.  * the pen color doesn't matter.
  73.  */
  74. int do_shift(const int numpix, const int numrows)
  75. {
  76.     float sinvalue,val2,radians,increment,prob;
  77.     int curpix,currow,tmprow,shift,drift, loopy, *ripple;
  78.     RGBColor color,test,test2,test3,test4;
  79.     const RGBColor white = {0xffff, 0xffff, 0xffff};
  80.     PatHandle dpat = GetPattern(16);
  81.     Pattern black;
  82.     int whee;
  83.     for (whee=0; whee<8; whee++) { black.pat[whee] = 0xffff; }
  84.     DetachResource((Handle)dpat);
  85.     HLock((Handle)dpat);
  86.     radians=0;
  87.     
  88.     for(currow=0; currow<numrows; currow+=2) /* for every rom in the window.... */
  89.         {
  90.         radians=Random()/1369;  /* herm.  this could be done better.  it currently puts a weird seed in radians to */
  91.         radians=fmod(radians,2*PI); /* minimize a sine wave appearance.  it doesnt work.  TABLE */
  92.         
  93.         for(curpix=0; curpix<numpix; curpix+=3) /* for every pixel in each row...*/
  94.             {
  95.             
  96.             GetCPixel(curpix,currow,&color);
  97.             if(curpix+1 < numpix) {
  98.                 GetCPixel(curpix+1,currow,&test); 
  99.                 if(curpix+2 < numpix) { 
  100.                     GetCPixel(curpix+2,currow,&test2); 
  101.                     if(curpix+3 < numpix) { 
  102.                         GetCPixel(curpix+3,currow,&test3); }
  103.                     else { 
  104.                         GetCPixel(curpix+2,currow,&test3); }
  105.                         }
  106.                 else { GetCPixel(curpix+1,currow,&test2); }
  107.                         }
  108.             else { GetCPixel(curpix,currow,&test); } /* this big ugly nested if .. else statement block basicaly makes */
  109.             /* sure we are still inside the window to avoid acquiring BlacTar(tm) from GetCPixel returning 0 from */
  110.             /* offscreen data */
  111.             
  112.              /* find hte "average color" of our dripping pixels */
  113.             color.red=((float)0.25*color.red)+((float)0.25*test.red)+((float)0.25*test2.red)+((float)0.25*test3.red);
  114.             color.blue=((float)0.25*color.blue)+((float)0.25*test.blue)+((float)0.25*test2.blue)+((float)0.25*test3.blue);
  115.             color.green=((float)0.25*color.green)+((float)0.25*test.green)+((float)0.25*test2.green)+((float)0.25*test3.green);
  116.              
  117.             if(color.red != white.red && color.blue != white.blue && color.green != white.green) /*  are we white? */
  118.                 {
  119.                 sinvalue = 4 * sin(radians);
  120.                 sinvalue+= 3 * sin(radians + (float)(PI/4));
  121.                 sinvalue+= 2 * sin(radians + (float)(PI/2.5));
  122.                 sinvalue+= 1 * sin(radians + (float)(PI / 1.5));
  123.                 radians+= 40 * PI / numpix;
  124.                 radians=fmod(radians,2*PI);
  125.                 sinvalue=fabs(sinvalue); 
  126.                 
  127.                 sinvalue  = (float)(currow/2) + (5 * sinvalue); /* this piece of magic code contains many magic numbers */
  128.                         /* it seems to generate the number of pixels that the piece drips */
  129.  
  130.                 for(loopy=0;loopy<sinvalue;loopy++)
  131.                     {
  132.                     
  133.                     GetCPixel(curpix,currow+loopy,&test);
  134.                     if(curpix+1 < numpix) 
  135.                         { 
  136.                         GetCPixel(curpix+1,currow+loopy,&test2);
  137.                         if(curpix+2 < numpix) 
  138.                             { 
  139.                             GetCPixel(curpix+2,currow+loopy,&test3); 
  140.                             if(curpix+3 < numpix) 
  141.                                 { 
  142.                                 GetCPixel(curpix+3,currow+loopy,&test4);
  143.                                 }
  144.                             else { GetCPixel(curpix+2,currow+loopy,&test4); }
  145.                             } 
  146.                         else { GetCPixel(curpix+1,currow+loopy,&test3); }
  147.                         }
  148.                     else { GetCPixel(curpix,currow+loopy,&test2); }/* this nasty whore makes sure we dont read from */
  149.                         /* a part of the windows that doesnt **REALLY** exist */
  150.                     
  151.                     /* get the average color of hte pixel about to be dripped on using averages of surrounding pixels. */
  152.                     test.red=(0.25*test4.red)+(0.25*test.red)+(0.25*test2.red)+(0.25*test3.red);
  153.                     test.blue=(0.25*test4.blue)+(0.25*test.blue)+(0.25*test2.blue)+(0.25*test3.blue);
  154.                     test.green=(0.25*test4.green)+(0.25*test.green)+(0.25*test2.green)+(0.25*test3.green);
  155.         
  156.         
  157.                     test.red= (0.8*test.red) + (color.red*0.2);  /* FUDGE ME!@!@!@!@!@!@!@! */
  158.                     test.blue= (0.8*test.blue) + (color.blue*0.2); /* controls how much original/fripped color is used */
  159.                     test.green= (0.8*test.green) + (color.green*0.2); /* FUDGE ME @!@!@!@!@!@ */
  160.                         
  161.                     #ifdef USERECTS 
  162.                     Rect rect;
  163.                     rect.top = currow+loopy;
  164.                     rect.left = curpix;
  165.                     rect.bottom = rect.top + 1;
  166.                     rect.right = curpix+2;
  167.                     RGBForeColor(&test);RGBBackColor(&test);
  168.                     FillRect(&rect,&qd.black);
  169.                     #else
  170.                     SetCPixel(curpix,currow+loopy,&test); /* OPTIMIZE ME!@!@! */
  171.                     SetCPixel(curpix+1,currow+loopy,&test);/* OPTIMIZE ME!@!@! */
  172.                     SetCPixel(curpix+2,currow+loopy,&test);/* OPTIMIZE ME!@!@! */
  173.             
  174.                     SetCPixel(curpix,currow+loopy+1,&test); /* OPTIMIZE ME!@!@! */
  175.                     SetCPixel(curpix+1,currow+loopy+1,&test);/* OPTIMIZE ME!@!@! */
  176.                     SetCPixel(curpix+2,currow+loopy+1,&test);/* OPTIMIZE ME!@!@! */
  177.                     #endif
  178.                 }
  179.                 
  180.             }
  181.  
  182.             tmprow=currow-4; /* generate wavy top.... perterbance TURN ME INTO A TABLE LOOKUP !@!@! */
  183.             tmprow-=2*sin(curpix/4); /* generate wavy top.... perterbance TURN ME INTO A TABLE LOOKUP !@!@! */
  184.             
  185.             SetCPixel(curpix,tmprow-3,&white); /* OPTIMIZE ME!@!@! */
  186.             SetCPixel(curpix+1,tmprow-3,&white);/* OPTIMIZE ME!@!@! */
  187.             SetCPixel(curpix+2,tmprow-3,&white);/* OPTIMIZE ME!@!@! */
  188.            
  189.             SetCPixel(curpix,tmprow-4,&white); /* OPTIMIZE ME!@!@! */
  190.             SetCPixel(curpix+1,tmprow-4,&white);/* OPTIMIZE ME!@!@! */
  191.             SetCPixel(curpix+2,tmprow-4,&white);/* OPTIMIZE ME!@!@! */
  192.             /* erase what we have left behind */
  193.  
  194.             }
  195.         PenPat(*dpat);
  196.         PenSize(3,3);
  197.         MoveTo(0,currow-5);
  198.         LineTo(numpix,currow-5);
  199.         PenPat(&black);
  200.         if (Button()) {  return(0); } /* for now, click to leave */
  201.         }
  202.         DisposeHandle((Handle)dpat);
  203. }
  204.  
  205. void PostStrNotification(Globals *gb,short rsrcId, short index)
  206. {
  207.     OSErr err;
  208.     
  209.     //DebugStr("\pnotification.");
  210. #if 0
  211.     GetIndString(gb->happystring,rsrcId, index);
  212.  
  213.     gb->currNotReq.qType = 8;
  214.     gb->currNotReq.nmSound = (Handle)-1L;
  215.     gb->currNotReq.nmStr = gb->happystring;
  216.     err = NMInstall(&gb->currNotReq);
  217.     if (err) {
  218.         SysBeep(1);
  219.     }
  220. #endif
  221. }
  222.  
  223. void IdleCall(Globals *gb)
  224. {
  225.     unsigned long nowtime;
  226.     GetDateTime(&nowtime);
  227.     if (nowtime - gb->lasttime > 75) {
  228.         gb->level++;
  229.         gb->lasttime = nowtime;
  230.     }
  231.     switch(gb->level) {
  232.         case 2:
  233.             if (gb->didNot < 3) {
  234.                 PostStrNotification(gb,257,0);
  235.                 gb->didNot = 3;
  236.             }
  237.             break;
  238.         case 4:
  239.             if (gb->didNot < 5) {
  240.                 PostStrNotification(gb,257,1);
  241.                 gb->didNot = 5;
  242.             }
  243.             break;
  244.         case 6:
  245.             if (gb->didNot < 7) {
  246.                 PostStrNotification(gb,257,2);
  247.                 gb->didNot = 7;
  248.             }
  249.             break;
  250.     }
  251. }
  252.  
  253.  
  254. //////////////////////////////////////////////////////////////////////////////////////////////
  255. //
  256. //    entry point
  257.  
  258. pascal long main(unsigned long message, Globals **globs, Rect *statusRect, GrafPtr statusPort) {
  259.     char            savedState;
  260.     Globals            *gb;
  261.     long            result;
  262.     Handle            theLastIcon;
  263.     Str255            helpString;
  264.  
  265.      EnterCodeResource();
  266.  
  267.     if ((long)globs > 0) {                                // if we have globals allocated,
  268.         savedState = HGetState((Handle)globs);            //    save the locked/unlocked state,
  269.         HLock((Handle)globs);                            //    lock the handle to the globals,
  270.         gb = *globs;                                    //    and point to the globals directly
  271.     }
  272.  
  273.     result = 0;                                            // just return zero for unknown messages
  274.     switch(message) {
  275.         case sdevInitModule:                            // initialize the module
  276.             if ((result = Initialize()) > 0) break;        //  and exit if successful
  277.             globs = (Globals **)result;
  278.             
  279.         case sdevCloseModule:                            // clean up before being closed
  280.             CleanUp(globs);
  281.             globs = 0L;
  282.             break;
  283.  
  284.         case sdevFeatures:                                // return feature bits
  285.             result = (1<<sdevWantMouseClicks)    |\
  286.                      (1<<sdevDontAutoTrack)        |\
  287.                      (1<<sdevHasCustomHelp);
  288.             break;
  289.  
  290.         case sdevGetDisplayWidth:                        // return display width
  291.             //result = (SmallIconWidth/2) +
  292.             //            SBGetBarGraphWidth(8) + kSlop;
  293.             result = SmallIconWidth;
  294.             break;
  295.  
  296.         case sdevPeriodicTickle:                        // periodic tickle when nothing else is happening
  297.             //theLastIcon = gb->lastIcon;                    //    save the last state
  298.             //GetCurrentIcon(gb);                            //    update everything
  299.             //if (theLastIcon == gb->lastIcon) break;        //    if everything's the same, just exit
  300.             //result += 1<<sdevHelpStateChange;            //    flag a state change in case we're displaying help
  301.  
  302.             //statusRect->right = statusRect->left + IconWidth;
  303.             //EraseRect(statusRect);                        // erase the icon
  304.             
  305.             /* May be wanting to do timing related melt stuff triggered from here. BRG */
  306.             IdleCall(gb);
  307.             break;
  308.  
  309.         case sdevDrawStatus:                            // update the interface in the Control Strip
  310.             DrawThermo(gb, statusRect);
  311.             break;
  312.  
  313.         case sdevMouseClick:                            // user clicked on the module's display area in the Control Strip
  314.             result = HandleMouseClick(gb, statusRect);
  315.             break;
  316.  
  317.         case sdevSaveSettings:                            // save changed settings
  318.             //result = SavePreferences(gb);
  319.             break;
  320.  
  321.         case sdevShowBalloonHelp:                        // display custom balloon help
  322.             SBGetDetachedIndString(helpString, gb->helpStrings, 0);
  323.             SBShowHelpString(statusRect, helpString);
  324.             break;
  325.     }
  326.  
  327.     if ((long)globs > 0)                                // if we have globals allocated,
  328.         HSetState((Handle)globs, savedState);            //    restore the locked/unlocked state
  329.  
  330.     ExitCodeResource();
  331.     return(result);
  332. }
  333.  
  334.  
  335. //////////////////////////////////////////////////////////////////////////////////////////////
  336. //
  337. //    initializes the module
  338.  
  339. long Initialize() {
  340.     short            i;
  341.     long            result;
  342.     Globals            **globs, *gb;
  343.     Str255            prefsResourceName;
  344.     SavedSettings    **preferences;
  345.     Handle            *theIconSuite;
  346.  
  347.     result = -1;                                        // assume failure
  348.  
  349.     if (! (globs = (Globals **)NewHandleClear(sizeof(Globals))))
  350.         return(MemError());                                // allocate the globals
  351.  
  352.     HLock((Handle)globs);                                // lock the globals while using them
  353.     gb = *globs;                                        //  and get a pointer to them
  354.  
  355.  
  356.     result = SBGetDetachIconSuite(&gb->thermoIcon, ThermoID, svAllSmallData);
  357.     if (result != noErr) { goto done; }
  358. #if 0
  359. //    load and detach the ‘up arrow’ picture
  360.  
  361.     if (! (gb->popupArrowPicture = GetPicture(PopupArrowPictID))) goto done;
  362.     DetachResource((Handle)gb->popupArrowPicture);
  363.  
  364. //    load and detach the configuration menu
  365.  
  366.     if (! (gb->configMenu = GetMenu(ConfigMenuID))) goto done;
  367.     DetachResource((Handle)gb->configMenu);
  368. #endif
  369.  
  370. //    load and detach the help strings
  371.  
  372.     if (! (gb->helpStrings = Get1Resource('STR#', HelpStringsID))) goto done;
  373.     DetachResource(gb->helpStrings);
  374. //    get the module's saved preferences, if any, and configure the module
  375.  
  376.     //gb->whichIcon = mShowFirstIcon;
  377.     /*SBGetDetachedIndString(prefsResourceName, gb->helpStrings, sPrefResourceName);
  378.     if (! SBLoadPreferences(prefsResourceName, (Handle *)&preferences) &&
  379.         ((**preferences).signature == 'Samp'))
  380.         gb->whichIcon = (**preferences).whichIcon;
  381. */
  382.     //GetCurrentIcon(gb);                                    // initialize which icon to draw
  383.     gb->level = 1; gb->goingdown = 1;
  384.     GetDateTime(&gb->lasttime);
  385.     gb->didNot =0;// no notifications done yet.
  386.     
  387.     HUnlock((Handle)globs);                                // unlock the globals
  388.  
  389.     result = (long)globs;                                // return the handle to the globals as the result
  390.  
  391. done:
  392.     return(result);                                        // return either a handle or an error code
  393. }
  394.  
  395.  
  396. //////////////////////////////////////////////////////////////////////////////////////////////
  397. //
  398. //    disposes of our storage before we get closed
  399.  
  400. void CleanUp(Globals **globs) {
  401.     Globals            *gb;
  402.  
  403.     if ((long)globs <= 0) return;
  404.  
  405.     HLock((Handle)globs);
  406.     gb = *globs;
  407.  
  408.     if (gb->thermoIcon) DisposeIconSuite(gb->thermoIcon, true);
  409.     if (gb->configMenu) DisposeMenu(gb->configMenu);
  410.     if (gb->helpStrings) DisposeHandle(gb->helpStrings);
  411.  
  412.     DisposeHandle((Handle)globs);
  413. }
  414.  
  415.  
  416. //////////////////////////////////////////////////////////////////////////////////////////////
  417. //
  418. //    draws the current icon and thermometer.
  419.  
  420. void DrawThermo(Globals *gb, Rect *statusRect)
  421. {
  422. //    short            arrowHeight;
  423.     Rect    iconRect;
  424.     Point    topLeft;
  425. //    draw the current icon
  426.     iconRect = *statusRect;
  427.     iconRect.right = SmallIconWidth+iconRect.left;
  428.     (void) PlotIconSuite(&iconRect, atNone, ttNone, gb->thermoIcon);
  429.     //topLeft.h = iconRect.right - (SmallIconWidth/2) + kSlop;
  430.     //topLeft.v = iconRect.top;
  431.     //SBDrawBarGraph(gb->level,MaxLevel,BarGraphSlopeRight,topLeft);
  432.     
  433. //    draw an ‘up arrow’ to show that the module has a popup menu
  434. /*
  435.     arrowHeight = (**gb->popupArrowPicture).picFrame.bottom - (**gb->popupArrowPicture).picFrame.top;
  436.     statusRect->left = statusRect->right;
  437.     statusRect->right += (**gb->popupArrowPicture).picFrame.right - (**gb->popupArrowPicture).picFrame.left;
  438.     statusRect->top = (statusRect->top + statusRect->bottom - arrowHeight) >> 1;
  439.     statusRect->bottom = statusRect->top + arrowHeight;
  440.     DrawPicture(gb->popupArrowPicture, statusRect);*/
  441. }
  442.  
  443.  
  444. //////////////////////////////////////////////////////////////////////////////////////////////
  445. //
  446. //    stuffs the icon suite handle of the current icon into gb->lastIcon,
  447. //    and the related help STR# index into gb->helpStringIndex
  448. #if 0
  449. void GetCurrentIcon(Globals *gb) {
  450.  
  451.     switch (gb->whichIcon) {
  452.         case mShowFirstIcon:
  453.             gb->lastIcon = gb->firstIcon;
  454.             gb->helpStringIndex = sFirstIconHelp;
  455.             break;
  456.  
  457.         case mShowSecondIcon:
  458.             gb->lastIcon = gb->secondIcon;
  459.             gb->helpStringIndex = sSecondIconHelp;
  460.             break;
  461.  
  462.         case mShowThirdIcon:
  463.             gb->lastIcon = gb->thirdIcon;
  464.             gb->helpStringIndex = sThirdIconHelp;
  465.             break;
  466.     }
  467. }
  468. #endif
  469.  
  470. #if 0
  471. Boolean IsWholeScreen(WindowPeek wl)
  472. {
  473.     WindowPtr wp = (WindowPtr)wl;
  474.     Rect foo;
  475.     GDHandle gdh = GetMainDevice();
  476.     int foowidth, screenwidth;
  477.     int fooheight, screenheight;
  478.     Boolean result;
  479.     char buf[255];
  480.     
  481.     foo = wp->portRect;
  482.     foowidth = foo.right - foo.left;
  483.     fooheight = foo.bottom - foo.top;
  484.     screenwidth = (*gdh)->gdRect.right - (*gdh)->gdRect.left;
  485.     screenheight = (*gdh)->gdRect.bottom - (*gdh)->gdRect.top;
  486.     
  487.     result = !((foowidth < screenwidth) || (fooheight < screenheight));
  488.     
  489.     sprintf(buf,"%dx%d being considered as %s the whole screen (%dx%d)",foowidth,fooheight,
  490.         result ? "being" : "not being", screenwidth,screenheight);
  491.     DebugStr(CtoPstr(buf));
  492.     return result;
  493. }
  494. #endif
  495. WindowPtr GetWindowToMelt(void)
  496. {
  497.     /* Pray. */
  498.     LayerPtr f;
  499.     WindowPeek wl;
  500.     char buf[255];
  501.     f = GetFirstLayer(); /* First layer is the Control Strip layer. */
  502.     //sprintf(buf,"first layer is 0x%lx, control strip, ignoring.",f);
  503.     //DebugStr(CtoPstr(buf));
  504.     for (; f; f = GetNextLayer(f)) {
  505.         //sprintf(buf,"next layer is 0x%lx.",f);
  506.         //DebugStr(CtoPstr(buf));
  507.         wl = (WindowPeek)GetFirstLayerWindow(f);
  508.         //sprintf(buf,"1st window (layer 0x%lx) is 0x%lx, %s visible, %s hilited.",f,wl,
  509.         //    wl->visible ? "is" : "not", wl->hilited ? "is" : "not");
  510.         //DebugStr(CtoPstr(buf));
  511.         for (; wl; wl = wl->nextWindow) {
  512.             //sprintf(buf,"next window (layer 0x%lx) is 0x%lx, %s visible, %s hilited.",f,wl,
  513.             //wl->visible ? "is" : "not", wl->hilited ? "is" : "not");
  514.             //DebugStr(CtoPstr(buf));
  515.             if (wl->refCon == 'sdev') {
  516.                 return (WindowPtr)wl;
  517.             }
  518.         }
  519.     }
  520.     return (WindowPtr)NULL;
  521. }
  522.  
  523.  
  524. //////////////////////////////////////////////////////////////////////////////////////////////
  525. //
  526. //    handles a mouse click on the module's display by tracking a popup menu to change settings
  527.  
  528. long HandleMouseClick(Globals *gb, Rect *statusRect) {
  529.     short            menuItem;
  530.     long            result=0;
  531.     short itemHit;
  532. #if 0
  533.     menuItem = SBTrackPopupMenu(statusRect, gb->aboutMenu);
  534.                                                     // call the utility routine to display a popup menu
  535.     CheckItem(gb->configMenu, gb->whichIcon, false);// uncheck the item for the previous icon
  536.  
  537.     result = 0;
  538.     if ((menuItem > 0) && (menuItem != gb->whichIcon)) {
  539.                                                     // if something was selected,
  540.         gb->whichIcon = menuItem;                    //    save the menu item number,
  541.         result = 1<<sdevNeedToSave;                    //     and notify the Control Strip that we need to update preferences
  542.     }
  543.     /* This is going away. */
  544.     if (gb->goingdown) {
  545.         gb->level--;
  546.         if (gb->level == 0) {
  547.             gb->goingdown = 0;
  548.         }
  549.     } else {
  550.         gb->level++;
  551.         if (gb->level == MaxLevel -1) {
  552.             gb->goingdown++;
  553.         }
  554.     }
  555.     
  556.     if (gb->level == MaxLevel -1)
  557. #endif
  558.     GrafPtr savePort = NULL;
  559.     WindowPtr frontWind = FrontWindow();
  560.     RgnHandle saveClip = NewRgn();
  561.     int height;
  562.     int width;
  563.     char buf[512];
  564.     DialogPtr dl = NULL;
  565.     
  566.     //Debugger();
  567.     //dl=GetNewDialog(256,NULL,(void *)-1L);
  568.     //if (!dl) return 0;
  569.     //do { SBModalDialogInContext(NULL, &itemHit); } while (itemHit != 1 && itemHit != 2);
  570.     //DisposeDialog(dl);
  571.     //if (itemHit != 1) return 0;
  572.     
  573.     if (!frontWind) {
  574.         frontWind = LMGetWMgrPort();
  575.         if (!frontWind) {
  576.             return 0;
  577.         }
  578.     }
  579.     height = frontWind->portRect.bottom - frontWind->portRect.top;
  580.     width = frontWind->portRect.right - frontWind->portRect.left;
  581.     //sprintf(buf,"Now ready to melt. frontWind=%lx savePort=%lx saveClip=%lx %dx%d",
  582.     //    frontWind,savePort,saveClip,width,height);
  583.     //DebugStr(CtoPstr(buf));
  584.     GetPort(&savePort);
  585.     SetPort(frontWind);
  586.     GetClip(saveClip);
  587.     ClipRect(&frontWind->portRect);
  588.     do_shift(width,height+8);
  589.     SetClip(saveClip);
  590.     SetPort(savePort);
  591.     DisposeRgn(saveClip);
  592.     SBShowHideControlStrip(false);
  593.     return(result);
  594. }
  595.  
  596.  
  597. //////////////////////////////////////////////////////////////////////////////////////////////
  598. //
  599. //    saves the module's settings so they'll be available across restarts
  600.  
  601. short SavePreferences(Globals *gb) {
  602.     short            result;
  603.     SavedSettings    **preferences;
  604.     Str255            prefsResourceName;
  605.  
  606.     preferences = (SavedSettings**)NewHandle(sizeof(SavedSettings));
  607.     if (! (result = MemError())) {                    // allocate a block to hold the settings
  608.  
  609.         (**preferences).signature = 'Samp';            // include a signature to verify it's ours
  610.         (**preferences).whichIcon = gb->whichIcon;    // stuff in the menu item number of the current icon
  611.  
  612.         SBGetDetachedIndString(prefsResourceName, gb->helpStrings, sPrefResourceName);
  613.                                                     // get the name of the preferences resource
  614.         result = SBSavePreferences(prefsResourceName, (Handle)preferences);
  615.                                                     // save the settings in the Control Strip's preferences file
  616.  
  617.         DisposeHandle((Handle)preferences);            // get rid of the block
  618.     }
  619.  
  620.     return(result);
  621. }
  622.